package com.cctc.rds.scheduler.server.schedule.hashedwheel;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

/**
 * 时间轮：哈希槽。
 */
public class HashedWheelBucket {
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class HashedWheelTimeout {
        private TimerTask task;
        private long deadline;
        private int rounds;
        private HashedWheelTimeout prev, next;

        public HashedWheelTimeout(TimerTask task, long deadline) {
            this.task = task;
            this.deadline = deadline;
        }
    }

    private HashedWheelTimeout head, tail;

    public void addTimeout(HashedWheelTimeout timeout) {
        if (head == null) {
            head = tail = timeout;
            return;
        }
        HashedWheelTimeout cur = head;
        while (cur != null && cur.rounds < timeout.rounds) {
            cur = cur.next;
        }
        if (cur != null) {
            timeout.next = cur.next;
            timeout.prev = cur;
            cur.next = timeout;
        } else {
            timeout.prev = tail;
            tail.next = timeout;
            tail = timeout;
        }
    }

    public List<TimerTask> removeTimeout(int curRounds) {
        List<TimerTask> ans = new ArrayList<>();
        HashedWheelTimeout cur = head;
        while (cur != null && cur.rounds <= curRounds) {
            ans.add(cur.task);
            cur = cur.next;
        }
        if (cur == null) head = tail = null;
        else head = cur;
        return ans;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder("[");
        HashedWheelTimeout cur = head;
        while (cur != null) {
            builder.append("{")
                    .append("task=").append(cur.task.getTaskKey()).append(",")
                    .append("rounds=").append(cur.rounds).append(",")
                    .append("deadline=").append(cur.deadline)
                    .append("},");
        }
        builder.append("]");
        return builder.toString();
    }
}
